#include "LcdProject.h"

LcdDriver lcdDriver;

void LcdDriver::DrawLine(uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint16 width)
{
	if (x1 == x2)
	{
		if (x1 >= CN_LCD_WIDTH)
		{
			return;
		}
		if (y1 <= y2)
		{
			if (y2 >= CN_LCD_HEITH)
			{
				return;
			}
			uint16 ex = x1 + width;
			if (ex > CN_LCD_WIDTH)
			{
				return;
			}

			ex = x1;
			uint16 bx = ex / 8;
			uint8 data;
			for (uint32 i = 0; i < width; i++)
			{
				data = 0x80 >> (ex % 8);
				bx = ex / 8;

				for (uint32 j = y1; j <=y2; j++)
				{
					picbuf[j][bx] |= data;
				}
				ex++;
			}
		}

	}
	else if(y1 == y2)
	{
		if (y1 >= CN_LCD_HEITH)
		{
			return;
		}
		if (x1 <= x2)
		{
			if (x2 >= CN_LCD_WIDTH)
			{
				return;
			}
			uint16 ey = y1 + width;
			if (ey > CN_LCD_HEITH)
			{
				return;
			}
			ey = y1;
			for (uint32 i = 0; i < width; i++)
			{
				uint8 data;
				for (uint32 j = x1; j <= x2; j++)
				{
					data = 0x80 >> (j % 8);
					picbuf[ey][j/8] |= data;
				}
				ey++;
			}
		}
	}

}

void LcdDriver::DrawRect(uint16 x1, uint16 y1, uint16 x2, uint16 y2, uint16 width)
{
	DrawLine(x1,y1,x1,y2,width);
	DrawLine(x1, y1, x2, y1, width);
	DrawLine(x2, y1, x2, y2, width);
	DrawLine(x1, y2, x2, y2, width);

}

void LcdDriver::DrawText(uint16 x, uint16 y, const uint8* text)
{
	if (x >= CN_LCD_WIDTH_BYTE)
	{
		return;
	}
	if (y >= CN_LCD_HEITH)
	{
		return;
	}
	uint8 data1,data2;
	while (0!=(data1 = *text))
	{
		if (data1 < 128)
		{
			for (uint32 i = 0; i < CN_FONT_HEIGHT; i++)
			{
				fontbuf[y+i][x] = gASSIC16[data1][i];
			}
			x++;
			text++;
		}
		else if ((data2 = text[1]) > 128)
		{
			uint8 sec = data1;
			sec -= 0xa1;
			uint8 loc = data2;
			loc -= 0xa1;
			uint32 seek = (94 * sec + loc) * sizeof(g_HZK16[0]);
			if (seek > g_HZK16Len)
			{
				return;
			}
			seek = (94 * sec + loc);
			for (uint32 i = 0; (i < CN_FONT_HEIGHT)&&((y+i)< CN_LCD_HEITH); i++)
			{
				fontbuf[y + i][x] = g_HZK16[seek][i];
			}
			x++;
			if (x >= CN_LCD_WIDTH_BYTE)
			{
				return;
			}
			for (uint32 i = 0;  ((y + i) < CN_LCD_HEITH)&&(i < CN_FONT_HEIGHT); i++)
			{
				fontbuf[y + i][x] = g_HZK16[seek][i+ CN_FONT_HEIGHT];
			}
			text += 2;
			x += 2;
		}
		else
		{
			break;
		}
		if (x >= CN_LCD_WIDTH_BYTE)
		{
			return;
		}
	}
}

void LcdDriver::DrawRotText(uint16 x, uint16 y, uint16 dispLen,const uint8* text)
{
	uint32 maxx = M_ItemNum(rotationbuf[0].buf[0]);
	if (x >= CN_LCD_WIDTH_BYTE)
	{
		return;
	}
	if (y >= CN_LCD_HEITH)
	{
		return;
	}

	rotline* line = &rotationbuf[y/ CN_FONT_HEIGHT];
	line->dispenable = 1;
	line->dstx = x;
	line->dsty = y;
	line->deltax = 0;
	line->deltay = 0;
	line->dispLen = dispLen;
	for (uint32 i = 0; i < CN_FONT_HEIGHT; i++)
	{
		for (uint32 j = 0; j < maxx; j++)
		{
			line->buf[i][j] = 0;
		}
	}

	uint8 data1, data2;
	
	while (0!=(data1 = *text))
	{
		if (data1 < 128)
		{
			for (uint32 i = 0; i < CN_FONT_HEIGHT; i++)
			{
				line->buf[i][x - line->dstx] = gASSIC16[data1][i];
			}
			x++;
			text++;
		}
		else if ((data2 = text[1]) > 128)
		{
			uint8 sec = data1;
			sec -= 0xa1;
			uint8 loc = data2;
			loc -= 0xa1;
			uint32 seek = (94 * sec + loc) * sizeof(g_HZK16[0]);
			if (seek > g_HZK16Len)
			{
				break;
			}
			seek = (94 * sec + loc);
			for (uint32 i = 0; i < CN_FONT_HEIGHT; i++)
			{
				line->buf[i][x- line->dstx] = g_HZK16[seek][i];
			}
			for (uint32 i = 0; i < CN_FONT_HEIGHT; i++)
			{
				line->buf[i][x - line->dstx + 1] = g_HZK16[seek][i + CN_FONT_HEIGHT];
			}
			text += 2;
			x += 2;
		}
		else
		{
			break;
		}
		if (x >= maxx)
		{
			break;
		}
	}
	line->strLen = x - line->dstx;

	if (line->strLen > line->dispLen)
	{
		line->rotenable = 1;
	}
	else
	{
		line->rotenable = 0;
	}

}

void LcdDriver::doLcdDraw()
{
	mixFont();

	for (uint32 i = 0; i < CN_LCD_HEITH; i++)
	{
		for (uint32 j = 0; j < CN_LCD_WIDTH_BYTE; j++)
		{
			dispbuf[i][j] = (fontbuf[i][j] ^ rvsbuf[i][j]) | picbuf[i][j];

			lcd_write_buf(j,i, dispbuf[i][j]);
		}
	}

}

void LcdDriver::doLcdLeftRotation()
{
	uint32 height = M_ItemNum(rotationbuf);

	for (uint32 i = 0; i < height; i++)
	{
		rotline* line = &rotationbuf[i];
		if (!line->dispenable)
		{
			line->deltax = 0;
			line->deltay = 0;
			continue;
		}
		if (line->rotenable)
		{
			uint32 x = line->dispLen + line->deltax;
			if (line->strLen > (x - 1))
			{
				line->deltax++;
			}
			else
			{
				line->deltax = 0;
			}
		}
	}
}

void LcdDriver::mixFont()
{
	uint32 height = M_ItemNum(rotationbuf);

	for (uint32 i = 0; i < height; i++)
	{
		rotline* line = &rotationbuf[i];
		if (!line->dispenable)
		{
			continue;
		}
		if (line->rotenable)
		{
			for (uint32 j = 0; j < CN_FONT_HEIGHT; j++)
			{
				for (uint32 k = 0; k < line->dispLen; k++)
				{
					fontbuf[line->dsty + j][line->dstx + k] = line->buf[j][k + line->deltax];
				}
			}
		}
		else
		{
			line->deltax = 0;
			line->deltay = 0;

			uint32 startx = line->dstx;
			uint32 endx = line->dstx;

			endx += line->strLen;

			if (endx > CN_LCD_WIDTH_BYTE)
			{
				endx = CN_LCD_WIDTH_BYTE;
			}

			for (uint32 j = 0; j < CN_FONT_HEIGHT; j++)
			{
				for (uint32 k = startx; k < endx; k++)
				{
					fontbuf[line->dsty + j][k] = line->buf[j][k- startx];
				}
			}
		}


	}
}

